#!/usr/bin/python
# pylint: disable-msg = 
'''
Created by Colin Gillespie <c.gillespie@ncl.ac.uk>
$LastChangedDate$ 

mrange is used to create arbitrary sums

'''

__revision__ = '$Rev$'

from copy import copy
from memoize import memoize

def mrange(min_values, max_values=None):
    '''
        Inputs: min_values, a list/tuple with the starting values
                    if not given, assumed to be zero
                max_values: a list/tuple with the ending values
        outputs: a tuple of values
    '''
    
    if not max_values:
        max_values = min_values
        min_values = [0 for i in max_values]
    indices_list = copy(min_values)

    #Yield the (0,0, ..,0) value
    yield tuple(indices_list)
    
    while(True):
        indices_list = __updateIndices(indices_list, min_values, max_values)
        if indices_list:
            yield tuple(indices_list)
        else:
            break#We're back at the beginning
   
def __updateIndices(indices_list, min_values, max_values):
    '''
        Update the list of indices
    '''
    for index in xrange(len(indices_list)-1, -1, -1):
        #If the indices equals the max values, the reset it and 
        #move onto the next value
        if not indices_list[index] == max_values[index]:
            indices_list[index] += 1
            return indices_list
        else:
            indices_list[index] = min_values[index]
    return False        

def cumRange(minvec, maxvec=None):  
    '''
        Similar to mrange. Used to generate cumulant equations
           
    '''
    if maxvec is None:
        maxvec = minvec
        minvec = [0] * len(maxvec)
    max_sum = max(maxvec)

    vec = list(minvec)
    unitpos = len(vec) - 1
    _tuple = tuple
    while 1:
        if sum(vec) < max_sum:
            vec[unitpos] += 1
        
        else:
            i = unitpos
            while 1:
                vec[i] = minvec[i]
                i -= 1
                if i == -1:
                    return
                vec[i] += 1

                if sum(vec) <= max_sum:
                    break
            
        yield _tuple(vec)

        
        


if __name__ == '__main__':

    for i in cumRange([2, 2, 2, 2]):
        print i
    for i in cumRange([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]):
        print i
